package com.yun.zf.system.utils;

import com.alibaba.fastjson.JSON;
import lombok.extern.java.Log;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.*;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
@Log
public class EsRestUtil {

    @Autowired
    private RestHighLevelClient rhlClient;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Autowired
    protected ElasticsearchOperations operations;

    /**
     * 创建索引
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T> boolean createIndex(Class<T> t) {
        IndexOperations indexOperations = operations.indexOps(t);
        boolean createIndexRes = indexOperations.create();
        if (!createIndexRes) {
            return false;
        }
        Document document = indexOperations.createMapping();
        return indexOperations.putMapping(document);
    }

    /**
     * 删除索引
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T> boolean deleteIndex(Class<T> t) {
        return operations.indexOps(t).delete();
    }

    /**
     * 判断索引是否存在
     *
     * @param t
     * @param <T>
     * @return
     */
    public <T> boolean indexExists(Class<T> t) {
        return operations.indexOps(t).exists();
    }

    /**
     * es添加数据
     *
     * @param o
     * @return
     */
    public String addDataRest(Object o,String index, String id ) {
        IndexQuery indexQuery = new IndexQueryBuilder()
                .withId(id)
                .withObject(o)
                .build();
        return elasticsearchRestTemplate.index(indexQuery, IndexCoordinates.of(index));
    }

    /**
     * 批量添加
     *
     * @param tList
     * @param id
     * @param index
     * @return
     */
    public List<IndexedObjectInformation> batchSave(List<Object> tList, String id, String index) {
        List<IndexQuery> indexQueryList = new ArrayList<>();
        tList.forEach(T -> {
            IndexQuery indexQuery = new IndexQuery();
            indexQuery.setObject(T);
            indexQuery.setId(id);
            indexQueryList.add(indexQuery);
        });
        return elasticsearchRestTemplate.bulkIndex(indexQueryList, IndexCoordinates.of(index));
    }

    /**
     * 根据主键更新es
     * @param index
     * @param object
     * @param id
     */
    public void updateDataById(Object object,String index, String id) {
        Document document =  Document.parse(JSON.toJSONString(object));
        UpdateQuery updateQuery = UpdateQuery.builder(id).withDocument(document).build();
        UpdateResponse response = elasticsearchRestTemplate.update(updateQuery, IndexCoordinates.of(index));
        System.out.println(response.getResult().name());
    }

    /**
     * 批量更新
     * @param index
     * @param object
     * @param ids
     */
    public void bulkUpdate(String index, Object object,String... ids) {
        Document document =  Document.parse(JSON.toJSONString(object));
        List<UpdateQuery> updateQueryList = new ArrayList<>();
        for (String id : ids) {
            UpdateQuery updateQuery = UpdateQuery.builder(id).withDocument(document).build();
            updateQueryList.add(updateQuery);
        }
        elasticsearchRestTemplate.bulkUpdate(updateQueryList, IndexCoordinates.of(index));
    }

    /**
     * 通过ID删除数据
     *
     * @param index 索引，类似数据库
     * @param id    数据ID
     * @return
     */
    public void deleteDataById(String id, String routing, String index) throws IOException {
        elasticsearchRestTemplate.delete(id, routing, IndexCoordinates.of(index));
    }

    public Map<String, Object> searchDataPage(String index,
                                              Class clazz ,NativeSearchQueryBuilder searchQueryBuilder) {
        Query  query =searchQueryBuilder.build();
        SearchHits<Class> searchHits= elasticsearchRestTemplate.search(query,clazz , IndexCoordinates.of(index));
        List<Class> data = searchHits.get().map(SearchHit::getContent).collect(Collectors.toList());
        long recordCount = searchHits.getTotalHits();
        Map<String, Object> map = new HashMap<>();
        map.put("total", recordCount);  //返回总匹配数
        map.put("data", data);
        return  map;
    }



    /**
     *
     * @param index
     * @param startPage
     * @param pageSize
     * @param clazz 返回映射数据
     * @return
     */
    public Map<String, Object> searchDataPage(String index, int startPage, int pageSize,
                                             Class clazz ,NativeSearchQueryBuilder searchQueryBuilder) {

        //es 中页数是从0 开始，所以这里做减一处理
        searchQueryBuilder.withPageable(PageRequest.of(startPage-1, pageSize));
        Query  query =searchQueryBuilder.build();

        SearchHits<Class> searchHits= elasticsearchRestTemplate.search(query,clazz , IndexCoordinates.of(index));

        List<Class> data = searchHits.get().map(SearchHit::getContent).collect(Collectors.toList());
        long recordCount = searchHits.getTotalHits();
        Map<String, Object> map = new HashMap<>();
        Long totalPage = (recordCount + pageSize -1) / pageSize;
        map.put("total", recordCount);  //返回总匹配数
        map.put("current", startPage); //当前页数
        map.put("totalPage", totalPage); //总页数
        map.put("records", data); // 匹配分页数据
        return  map;
    }

    public CompletionSuggestion termSuggest(String index , SuggestBuilder suggestBuilder) {
        Suggest suggest =   elasticsearchRestTemplate.suggest(suggestBuilder, IndexCoordinates.of(index)).getSuggest();
        //搜索结果状态信息
        List<Map<String,String>> list = new ArrayList<>();
        // 取出结果
        return suggest.getSuggestion("community-suggest");

        /*for (CompletionSuggestion.Entry entry : termSuggestion.getEntries()) {
            log.info("text: " + entry.getText().string());
            for (CompletionSuggestion.Entry.Option option : entry) {
                String suggestText = option.getText().string();
                String id = option.getHit().getId();
                String cityCode = option.getHit().getSourceAsMap().get("cityCode").toString();
                String provinceCode =option.getHit().getSourceAsMap().get("provinceCode").toString();
                String regionCode =option.getHit().getSourceAsMap().get("regionCode").toString();
                String streetCode =option.getHit().getSourceAsMap().get("streetCode").toString();
                Map<String,String> map = new HashMap();
                map.put("id",id);
                map.put("cityCode",cityCode);
                map.put("provinceCode",provinceCode);
                map.put("suggestText",suggestText);
                map.put("regionCode",regionCode);
                map.put("streetCode",streetCode);
                list.add(map);
                log.info("   suggest option : " + suggestText);
            }
        }
        return list;*/
    }


}
